﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Niti.OrderManage.DTO;
using Niti.OrderManage.Eto;
using Niti.OrderManage.OrderManage;
using Niti.OrderManage.OrderManage.Enum;
using Niti.OrderManage.OrderManage.Repositories;
using Niti.OrderManage.OrderManage.ValueObject;
using Niti.OrderManage.ToolKits.Base;
using Niti.OrderManage.ToolKits.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Uow;
using static Niti.OrderManage.NitiOrderManageConsts;

namespace Niti.OrderManage.Order.Impl
{
    [ApiController]
    [Route("[controller]/[action]")]
    [ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
    public class ReceiptOrderManageService : NitiOrderManageApplicationServiceBase,
        ILocalEventHandler<EntityDeletingEventData<Commodity>>
    {



        private readonly IReceiptOrderRepository _receiptOrderRepository;
        private readonly IReceiptOrderLineItemRepository _receiptOrderLineItemRepository;

        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly ILogger _logger;
        private readonly ILocalEventBus _localEventBus;

        public ReceiptOrderManageService(
            IReceiptOrderRepository receiptOrderRepository,
            IReceiptOrderLineItemRepository receiptOrderLineItemRepository,
            IUnitOfWorkManager unitOfWorkManager,
            ILogger<ReceiptOrderManageService> logger,
            ILocalEventBus localEventBus)
        {
            _receiptOrderRepository = receiptOrderRepository;
            _receiptOrderLineItemRepository = receiptOrderLineItemRepository;
            _unitOfWorkManager = unitOfWorkManager;
            _logger = logger;
            _localEventBus = localEventBus;
        }


        #region 入库订单操作
        /// <summary>
        /// 新增入库订单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ServiceResult<string>> InsertReceiptOrderAsync(string code)
        {
            var result = new ServiceResult<string>();
            try
            {
                //校验采购订单是否存在
                //发布查询采购订单事件
                IOrder order = await PublishSelectOrderAsync(code);

                #region 拿到订阅查询结果处理操作
                var entityExist = order;
                if (entityExist == null)
                {
                    result.IsFailed(ResponseText.INSERT_FAILED + ",不存在该采购订单或者该采购订单未审核");
                    return result;
                }

                //校验该采购单所对应的入库单是否存在
                var receiptEntity = await _receiptOrderRepository.FindAsync(x => x.Code == code);
                if (receiptEntity != null)
                {
                    result.IsFailed(ResponseText.INSERT_FAILED + ",已存在该采购订单所对应的入库订单");
                    return result;
                }

                //入库订单
                string receiptcode = Guid.NewGuid().ToString();
                var order_Supplier = new Order_Supplier(entityExist.Supplier_Code, entityExist.Supplier_SName);
                var orderentity = new ReceiptOrder(receiptcode, code, entityExist.Count, entityExist.TotalPrice, entityExist.Title, order_Supplier);
                //入库单明细
                List<ReceiptOrderLineItem> list = new List<ReceiptOrderLineItem>();
                //入库单明细商品编号
                List<string> commodityCodeList = new List<string>();
                //订单明细   
                foreach (var item in entityExist.OrderLineItem)
                {
                    //订单明细商品
                    var orderLineItem_Commodity = new OrderLineItem_Commodity(item.Commodity_Code, item.Commodity_CName, item.Commodity_CPrice);
                    ReceiptOrderLineItem receiptOrderLineItem = new ReceiptOrderLineItem(receiptcode, item.LineNumber, orderLineItem_Commodity, item.Count);
                    list.Add(receiptOrderLineItem);
                    commodityCodeList.Add(item.Commodity_Code);
                }
                await _receiptOrderLineItemRepository.InsertManyAsync(list);
                var post = await _receiptOrderRepository.InsertAsync(orderentity);
                await _unitOfWorkManager.Current.SaveChangesAsync();
                if (post == null)
                {
                    result.IsFailed(ResponseText.INSERT_FAILED);
                    return result;
                }

                #endregion

                result.IsSuccess(post.ReceiptCode, ResponseText.INSERT_SUCCESS);

            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                result.IsFailed(ResponseText.INSERT_FAILED);
            }

            return result;
        }


        /// <summary>
        ///删除入库订单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>

        [HttpDelete]
        public async Task<ServiceResult<string>> DeleteReceiptOrderAsync(string receiptcode)
        {
            var result = new ServiceResult<string>();
            try
            {
                //查询是否有该入库订单
                var entityExist = await _receiptOrderRepository.FindAsync(x => x.ReceiptCode == receiptcode);
                if (entityExist == null)
                {
                    result.IsFailed(ResponseText.DELETE_FAILED + ",没有该入库订单");
                    return result;
                }
                //状态校验
                if (entityExist.IsDraft != OrderStatusCode.Draft)
                {
                    result.IsFailed(ResponseText.DELETE_FAILED + ",该入库订单已审核");
                    return result;
                }

                //订单明细   
                var orderLineItementity = _receiptOrderLineItemRepository.Where(x => x.ReceiptOrderCode == receiptcode).ToList();

                await _receiptOrderLineItemRepository.DeleteManyAsync(orderLineItementity);
                await _receiptOrderRepository.DeleteAsync(entityExist);
                await _unitOfWorkManager.Current.SaveChangesAsync();

                result.IsSuccess(ResponseText.DELETE_SUCCESS);



            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                result.IsFailed(ResponseText.DELETE_FAILED);
            }

            return result;
        }


        /// <summary>
        /// 修改明细
        /// </summary>
        /// <param name="code">入库订单号</param>
        /// <param name="dto">明细</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ServiceResult<string>> ChangeLineItemAsync(string receiptcode, ReceiptItemDto dto)
        {
            var result = new ServiceResult<string>();
            try
            {
                //查询是否有该订单
                var entityExist = await _receiptOrderRepository.FindAsync(x => x.ReceiptCode == receiptcode);
                if (entityExist == null)
                {
                    result.IsFailed(ResponseText.UPDATE_FAILED + ",不存在该入库订单");
                    return result;
                }
                //状态校验
                if (entityExist.IsDraft != OrderStatusCode.Draft)
                {
                    result.IsFailed(ResponseText.UPDATE_FAILED + ",该订单已审核");
                    return result;
                }
                //修改明细
                entityExist.ReceiptOrderLineItem = _receiptOrderLineItemRepository.Where(x => x.ReceiptOrderCode == receiptcode).ToList();
                //校验明细商品数量
                if (dto.RealityCount < 0)
                {
                    result.IsFailed(ResponseText.UPDATE_FAILED + ",入库数量不能小于0");
                    return result;
                }
                entityExist.ChangeItem(dto.LineNumber, dto.RealityCPrice, dto.RealityCount, entityExist.ReceiptOrderLineItem);
                await _receiptOrderLineItemRepository.UpdateManyAsync(entityExist.ReceiptOrderLineItem);
                var post = await _receiptOrderRepository.UpdateAsync(entityExist);
                await _unitOfWorkManager.Current.SaveChangesAsync();
                if (post == null)
                {
                    result.IsFailed(ResponseText.UPDATE_FAILED);
                    return result;
                }

                result.IsSuccess(ResponseText.UPDATE_SUCCESS);

            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                result.IsFailed(ResponseText.UPDATE_FAILED);
            }
            return result;
        }

        /// <summary>
        /// 修改入库订单
        /// </summary>
        /// <param name="receiptcode"></param>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ServiceResult<string>> ChangeLineItemsAsync(ReceiptItemsDto dto)
        {
            var result = new ServiceResult<string>();
            try
            {
                //查询是否有该订单
                var entityExist = await _receiptOrderRepository.FindAsync(x => x.ReceiptCode == dto.ReceiptCode);
                if (entityExist == null)
                {
                    result.IsFailed(ResponseText.UPDATE_FAILED + ",不存在该入库订单");
                    return result;
                }
                //状态校验
                if (entityExist.IsDraft != OrderStatusCode.Draft)
                {
                    result.IsFailed(ResponseText.UPDATE_FAILED + ",该订单已审核");
                    return result;
                }
                //修改明细
                entityExist.ReceiptOrderLineItem = _receiptOrderLineItemRepository.Where(x => x.ReceiptOrderCode == dto.ReceiptCode).ToList();
                foreach (var item in dto.Items)
                {
                    //校验明细商品数量
                    if (item.RealityCount < 0)
                    {
                        result.IsFailed(ResponseText.UPDATE_FAILED + ",入库数量不能小于0");
                        return result;
                    }
                    entityExist.ChangeItem(item.LineNumber, item.RealityCPrice, item.RealityCount, entityExist.ReceiptOrderLineItem);
                }
                await _receiptOrderLineItemRepository.UpdateManyAsync(entityExist.ReceiptOrderLineItem);
                var post = await _receiptOrderRepository.UpdateAsync(entityExist);
                await _unitOfWorkManager.Current.SaveChangesAsync();
                if (post == null)
                {
                    result.IsFailed(ResponseText.UPDATE_FAILED);
                    return result;
                }

                result.IsSuccess(ResponseText.UPDATE_SUCCESS);

            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                result.IsFailed(ResponseText.UPDATE_FAILED);
            }
            return result;
        }

        /// <summary>
        /// 入库订单审核
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ServiceResult<string>> CheckReceiptOrderAsync(string receiptcode)
        {
            var result = new ServiceResult<string>();
            try
            {
                Dictionary<string, int> dic = new Dictionary<string, int>();
                //查询是否有该订单
                var entityExist = await _receiptOrderRepository.FindAsync(x => x.ReceiptCode == receiptcode);
                if (entityExist == null)
                {
                    result.IsFailed("不存在该入库订单");
                    return result;
                }
                //状态校验
                if (entityExist.IsDraft != OrderStatusCode.Draft)
                {
                    result.IsFailed("该订单已审核");
                    return result;
                }
                entityExist.IsDraft = OrderStatusCode.NoDraft;
                entityExist.CheckTime = DateTime.Now;
                entityExist.ReceiptOrderLineItem = _receiptOrderLineItemRepository.Where(x => x.ReceiptOrderCode == receiptcode).OrderBy(x => x.Commodity_Code).ToList();
                foreach (var item in entityExist.ReceiptOrderLineItem)
                {
                    dic.Add(item.Commodity_Code, item.RealityCount);
                }

                //发布商品入库事件
                await PublishCheckOrderAsync(dic);

                #region 废弃
                // var list = _commodityRepository.Where(x => dic.Keys.Contains(x.Code)).OrderBy(x => x.Code).ToList();

                //foreach (var commodity in list)
                //{
                //    commodity.Count += dic[commodity.Code];
                //}
                // await _commodityRepository.UpdateManyAsync(list); 
                #endregion

                var post = await _receiptOrderRepository.UpdateAsync(entityExist);
                await _unitOfWorkManager.Current.SaveChangesAsync();
                if (post == null)
                {
                    result.IsFailed("审核失败");
                    return result;
                }
                result.IsSuccess("审核成功");


            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                result.IsFailed("审核失败");
            }
            return result;
        }



        /// <summary>
        /// 根据入库订单号查询订单
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ServiceResult<ReceiptOrderDto>> GetReceiptOrderAsync(string receiptcode)
        {
            ServiceResult<ReceiptOrderDto> result = new ServiceResult<ReceiptOrderDto>();
            try
            {
                var entity = await _receiptOrderRepository.FindAsync(x => x.ReceiptCode == receiptcode);
                if (entity == null)
                {
                    result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("订单号", receiptcode));
                    return result;
                }
                entity.ReceiptOrderLineItem = _receiptOrderLineItemRepository.Where(x => x.ReceiptOrderCode == receiptcode).ToList();
                result.IsSuccess("ok");
                //返回dto
                ReceiptOrderDto dto = new ReceiptOrderDto()
                {
                    Code = entity.Code,
                    ReceiptCode = entity.ReceiptCode,
                    CreationTime = entity.CreationTime,
                    Supplier_Code = entity.Supplier_Code,
                    Supplier_SName = entity.Supplier_SName,
                    Title = entity.Title,
                    Count = entity.Count,
                    TotalPrice = entity.TotalPrice,
                    RealityCount = entity.RealityCount,
                    RealityTotalPrice = entity.RealityTotalPrice,
                    UpdateTime = entity.UpdateTime
                };
                //订单明细   
                List<ReceiptOrderLineItemDto> list = new List<ReceiptOrderLineItemDto>();
                foreach (var item in entity.ReceiptOrderLineItem)
                {
                    list.Add(new ReceiptOrderLineItemDto
                    {
                        ReceiptOrderCode = item.ReceiptOrderCode,
                        Commodity_CName = item.Commodity_CName,
                        Commodity_Code = item.Commodity_Code,
                        Commodity_CPrice = item.Commodity_CPrice,
                        CreationTime = item.CreationTime,
                        LineNumber = item.LineNumber,
                        Count = item.Count,
                        Subtotal = item.Subtotal,
                        RealityCount = item.RealityCount,
                        RealitySubtotal = item.RealitySubtotal,
                        UpdateTime = item.UpdateTime
                    });
                }
                dto.ReceiptOrderLineItem = list;
                result.Result = dto;

            }
            catch (Exception ex)
            {
                result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("订单号", receiptcode));
                _logger.LogError(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 高级查询
        /// </summary>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize"></param>
        /// <param name="title"></param>
        /// <param name="supplier_Code"></param>
        /// <param name="supplier_SName"></param>
        /// <param name="isDraft"></param>
        /// <param name="beginTime"></param>
        /// <param name="endtime"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ServiceResult<PagedList<ReceiptOrderDto>>> GetReceiptOrderListAsync(int pageIndex = 1, int pageSize = 10, string title = "", string supplier_Code = "", string supplier_SName = "", OrderStatusCode isDraft = OrderStatusCode.All, string beginTime = "1990-10-15", string endtime = "")
        {
            var result = new ServiceResult<PagedList<ReceiptOrderDto>>();
            try
            {
                //校验时间
                if ((!string.IsNullOrEmpty(beginTime) && !string.IsNullOrEmpty(endtime)) && (DateTime.Compare(Convert.ToDateTime(beginTime), Convert.ToDateTime(endtime)) > 0))
                {
                    result.IsFailed("查询失败,开始时间大于结束时间");
                    return result;
                }

                if (string.IsNullOrEmpty(endtime))
                    endtime = DateTime.Now.ToShortDateString();




                var entitylist = (from orders in await _receiptOrderRepository.GetListAsync()
                                  where (string.IsNullOrEmpty(title) || orders.Title.Contains(title))
                                         && (string.IsNullOrEmpty(supplier_Code) || orders.Supplier_Code == supplier_Code)
                                         && (string.IsNullOrEmpty(supplier_SName) || orders.Supplier_SName == supplier_SName)
                                         && ((isDraft == OrderStatusCode.All) || orders.IsDraft == isDraft)
                                         && ((string.IsNullOrEmpty(beginTime) && string.IsNullOrEmpty(endtime)) || (orders.CreationTime >= Convert.ToDateTime(beginTime) && orders.CreationTime <= Convert.ToDateTime(endtime).AddDays(1)))
                                  orderby orders.CreationTime descending
                                  select new ReceiptOrderDto
                                  {
                                      Code = orders.Code,
                                      ReceiptCode = orders.ReceiptCode,
                                      Title = orders.Title,
                                      Supplier_Code = orders.Supplier_Code,
                                      Supplier_SName = orders.Supplier_SName,
                                      Count = orders.Count,
                                      TotalPrice = orders.TotalPrice,
                                      RealityCount = orders.RealityCount,
                                      RealityTotalPrice = orders.RealityTotalPrice,
                                      CreationTime = orders.CreationTime,
                                      IsDraft = orders.IsDraft
                                  }).OrderByDescending(m => m.CreationTime);
                if (pageIndex < 0 || pageSize < 0)
                {
                    var list = entitylist.ToList();
                    result.IsSuccess(new PagedList<ReceiptOrderDto>(list.Count, list));
                }
                else
                {
                    var list = entitylist.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
                    result.IsSuccess(new PagedList<ReceiptOrderDto>(list.Count, list.ToList()));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                result.IsFailed("查询失败");
            }

            return result;
        }


        #endregion

        #region 订阅事件
        /// <summary>
        /// 订阅商品删除事件
        /// </summary>
        /// <param name="eventData"></param>
        /// <returns></returns>
        [NonAction]
        public async Task HandleEventAsync(EntityDeletingEventData<Commodity> eventData)
        {
            try
            {
                //如果存在订单包含该商品，不能删除
                var receiptorder = await _receiptOrderRepository.GetListAsync(x => x.IsDraft == OrderStatusCode.NoDraft);
                if (receiptorder != null)
                {
                    foreach (var item in receiptorder)
                    {
                        var commoditys = await _receiptOrderLineItemRepository.GetListAsync(x => x.ReceiptOrderCode == item.ReceiptCode);
                        if (commoditys != null)
                        {
                            foreach (var commodity in commoditys)
                            {
                                if (commodity.Commodity_Code == eventData.Entity.Code)
                                {
                                    throw new NotImplementedException("入库订单：" + item.ReceiptCode + ",存在该商品" + eventData.Entity.Code);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                throw new NotImplementedException(ex.ToString());
            }
            await Task.CompletedTask;
        }


        /// <summary>
        /// 订阅供应商删除事件
        /// </summary>
        /// <param name="eventData"></param>
        /// <returns></returns>
        [NonAction]
        public async Task HandleEventAsync(EntityDeletingEventData<Supplier> eventData)
        {
            try
            {
                //如果存在订单包含该供应商，不能删除
                var order = await _receiptOrderRepository.FindAsync(x => x.IsDraft == OrderStatusCode.NoDraft && x.Supplier_Code == eventData.Entity.Code);
                if (order != null)
                {
                    throw new NotImplementedException("入库订单：" + order.Code + ",存在该供应商" + eventData.Entity.Code);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.ToString());
                throw new NotImplementedException(ex.ToString());
            }
        }
        #endregion

        #region 发布事件
        /// <summary>
        /// 发布查询采购订单事件
        /// </summary>
        /// <param name="code">采购订单编号</param>
        private async Task<IOrder> PublishSelectOrderAsync(string code)
        {
            CheckOrderExistsEto eto = new CheckOrderExistsEto(code);
            //发布查询事件
            await _localEventBus.PublishAsync(eto);

            return eto.Order;
        }

        /// <summary>
        /// 发布订单审核后商数量变化
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        private async Task PublishCheckOrderAsync(Dictionary<string, int> dic)
        {
            CheckedCommodityCountEto eto = new CheckedCommodityCountEto(dic);
            await _localEventBus.PublishAsync(eto);
        }

        #endregion
    }
}
